﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using AutoMapper;
using System.Web.Routing;

using MvcContrib;
using System.Text;
using Dinamico.Service;
using Dinamico.Models;
using N2.Web.Mvc;
using System.Configuration;
using N2;
using System.IO;
using Dynamico.Service;

namespace Dinamico.Controllers
{
    public class ArticleController : Controller
    {

        private IBasketService basketService;
        private ILogger logger;

        public ArticleController(IBasketService basketService, ILogger logger)
        {

            this.basketService = basketService;
            this.logger = logger;

            //Mapper.CreateMap<CategoryData, CategoryModel>();
            //Mapper.CreateMap<AssortmentInfoData, AssortmentInfoModel>();
            //Mapper.CreateMap<PriceData, PriceModel>();
            //Mapper.CreateMap<ArticleData, ArticleModel>();
        }

        //
        // GET: Articles/{category}/{page}        
        //public ActionResult Index(string category, int? page)
        //{
        //    ViewData[Const.Article.ROUTE_CATEGORY] = null;
        //    CategoryModel categoryModel = null;

        //    List<ArticleModel> articles = new List<ArticleModel>();            

        //    if (!String.IsNullOrEmpty(category))
        //    {
        //        ViewData[Const.Article.ROUTE_CATEGORY] = categoryModel = GetCategoryByRouteData();

        //        List<ArticleData> articlesDataForCategory = articleService.GetArticlesForCategory(category)
        //                    .OrderBy(_ => _.Name.Trim())
        //                    .ToList();

        //        articles = Mapper.Map<List<ArticleData>, List<ArticleModel>>(articlesDataForCategory);
        //    }            

        //    //Map to View Model
        //    PagedList<ArticleModel> results = articles.AsQueryable().ToPagedList(page ?? 1, 
        //        (categoryModel != null && !categoryModel.IsVirtual) ? Const.Article.ARTICLES_LIST_PAGE_SIZE : articles.Count);

        //    if (results.Count == 0)
        //    {
        //        return View("CategoryInfo", ViewData[Const.Article.ROUTE_CATEGORY]);
        //    }
        //    else
        //    {
        //        return View("Index", results);
        //    }
        //}

        // GET: "Article/{" + Const.Route.CategoryRouteDataKey + "}/{encodedName}/{articleId}"
        //public ActionResult Details(string category, string encodedName, int? articleId)
        //{
        //    ArticleModel article = null;

        //    if (articleId.HasValue && articleId.Value > 0 
        //        && !String.IsNullOrEmpty(category))
        //    {
        //        ///Users may enter any "kind" of Url directly
        //        if (!String.IsNullOrEmpty(encodedName))
        //        {
        //            //ArticleData articleData = articleService.GetArticleByCategoryAndName(category, encodedName);
        //            ArticleData articleData = articleService.GetArticleById(articleId.Value);

        //            if (articleData != null)
        //            {
        //                article = Mapper.Map<ArticleData, ArticleModel>(articleData);
        //            }
        //        }
        //    }
        //    return View("Details", article);
        //}

        #region NO SCRIPT ACTION
        // POST: NO JAVASCRIPT SCRIPT ENABLED IN BROSER
        [HttpPost]
        public ActionResult AddToBasketNoScript(int? articleId)
        {
            if (ModelState.IsValid && articleId.HasValue && articleId.Value > 0)
            {
                //var articleData = null; articleService.GetArticleById(articleId.Value);
                //if (articleData != null)
                //{
                //    var article = Mapper.Map<ArticleData, ArticleModel>(articleData);

                //    var userQuantity = Request.Form["Quantity"];
                //    var userSizeType = Request.Form["SizeTypeSel"];

                //    bool validSizeName = article.PriceList.Any(_ => _.SizeName.Equals(userSizeType));                   

                //    double quantityDouble = 1;
                //    if (!Double.TryParse(userQuantity, out quantityDouble)) quantityDouble = 1;

                //    var articleInputModel = new ArticleInputModel()
                //    {
                //        ArticleId = article.ArticleID,
                //        Quantity = quantityDouble,
                //        SizeName = validSizeName ? userSizeType : article.CurrentPrice.SizeName
                //    };

                //    BasketArticleModel basketArticle = null;
                //    try
                //    {
                //        //Add top basket
                //        basketArticle = basketService.Add(articleInputModel);
                //    }
                //    catch (ArgumentException ex)
                //    {
                //        return Content(ex.ToString());
                //    }
                //    return RedirectToRoute(Const.Route.Basket_List, new { category = ArticleService.GetEncodedName(article.Category.Name) });
                //}
            }
            if (Request.UrlReferrer != null && !String.IsNullOrEmpty(Request.UrlReferrer.AbsolutePath))
            {
                return Redirect(Server.HtmlEncode(Request.UrlReferrer.AbsolutePath));
            }
            else
            {
                return Content("<h2>" + "ArticlesNotFound" + "</h2>");
            }
        }
        #endregion

        // POST: JSON
        [HttpPost]
        public ActionResult AddToBasket(ArticleInputModel articleInputModel)
        {
            if (ModelState.IsValid && articleInputModel != null
                && !String.IsNullOrEmpty(articleInputModel.Id))
            {
                BasketArticleModel basketArticle = null;
                BasketItemModel basketItem = null;

                try
                {
                    //Add top basket
                    var gproduct = N2.Find.Items
                        .Where.ID.Eq(Convert.ToInt32(articleInputModel.Id))
                        .Select().SingleOrDefault();


                    if (gproduct is PartProductGoogleModel)
                    {
                        basketArticle = basketService.Add(articleInputModel);

                        basketItem = BasketService.ConvertArticle(gproduct as PartProductGoogleModel);


                        basketItem.Quantity = basketArticle.Quantity;
                        // 
                    }
                }
                catch (ArgumentException ex)
                {
                    logger.Error(ex);
                }
                catch (FormatException ex)
                {
                    logger.Error(ex);
                }
                catch (OverflowException ex)
                {
                    logger.Error(ex);
                }

                return Json(basketItem);
            }

            return Content("An error occured!");
        }

        // POST: JSON
        [HttpPost]
        public ActionResult AddAllIntoBasket(List<ArticleInputModel> articleInputModelList)
        {
            var errorOutput = new StringBuilder("An error occured!");

            if (ModelState.IsValid && articleInputModelList != null && articleInputModelList.Count > 0)
            {
                foreach (var item in articleInputModelList)
                {
                    if (item != null)
                    {
                        try
                        {
                            //Add to basket
                            basketService.Add(item);
                        }
                        catch (ArgumentException ex)
                        {
                            errorOutput.AppendLine(ex.ToString());
                            return Content(errorOutput.ToString());
                        }
                    }
                }
                return Json(new JsonOutputModel() { Message = "Action succeeded!" });
            }

            return Content(errorOutput.ToString());
        }

        // POST: JSON
        [HttpPost]
        public ActionResult RememberArticle(ArticleInputModel articleInputModel)
        {
            //if (ModelState.IsValid && articleInputModel != null && articleInputModel.ArticleId > 0)
            //{
            //    return Json(articleInputModel);
            //}
            return Content("An error occured!");
        }

        //[ChildActionOnly]
        //public ActionResult PageTitleByCategory()
        //{
        //    var sb = new StringBuilder(String.Empty);

        //    var cat = GetCategoryByRouteData();
        //    if (cat != null)
        //    {
        //        sb.Append(cat.Name);
        //    }
        //    else
        //    {
        //        sb.Append(Resources.Article.Index.Title);
        //    }

        //    return Content(sb.ToString());
        //} 
        public ActionResult Hello()
        {

            return Content("heloo!");
        }
        //not used
        public ActionResult Category(string category, int? page, int pageSize)
        {
            return Json(CategoryList(category, page, pageSize,null));
        }
        #region Search

        private static IEnumerable<PartProductGoogleModel> sigleton = null;  
        private IEnumerable<PartProductGoogleModel> GetAllProducts() {

            if (sigleton == null)
            {
                sigleton = N2.Find.Items.Where.Type.Eq(typeof(PartProductGoogleModel))
                //.And.
                //State.Eq(ContentState.Published)
                    //Or.State.Eq(ContentState.None)
                .Select<PartProductGoogleModel>().ToList();
            }
        return sigleton;
        
        }

        private IList<BasketItemModel> CategoryList(string category, int? page, int pageSize, string atrybutes)
        {

            IEnumerable<PartProductGoogleModel> all = GetAllProducts();

            IList<BasketItemModel> products_all = new List<BasketItemModel>();
            //m/
            Dictionary<string,PartProductGoogleModel> byCategory = new Dictionary<string,PartProductGoogleModel>();

            if (!string.IsNullOrEmpty(atrybutes))
            {

            if (atrybutes.ToLower().Contains('h'))
                {
                    IList<PartProductGoogleModel> byCat = (from x in all
                                                           where x.AtrH.Contains(category)
                                                           select x).ToList();
                    foreach (var prod in byCat)
                    {
                        if (!byCategory.ContainsKey(prod.Name))
                        {
                            byCategory.Add(prod.Name, prod);
                        }
                    }
            }
            if (atrybutes.ToLower().Contains('g'))
            {
                IList<PartProductGoogleModel> byCat = (from x in all
                                                       where x.AtrG.Contains(category)
                                                       select x).ToList();
                foreach (var prod in byCat) {
                    if (!byCategory.ContainsKey(prod.Name)) {
                        byCategory.Add(prod.Name, prod);
                    }
                }
            }
            if (atrybutes.ToLower().Contains('i'))
            {
                IList<PartProductGoogleModel> byCat = (from x in all
                                                       where x.AtrI.Contains(category)
                                                       select x).ToList();
                foreach (var prod in byCat)
                {
                    if (!byCategory.ContainsKey(prod.Name))
                    {
                        byCategory.Add(prod.Name, prod);
                    }
                }
            }

            if (atrybutes.ToLower().Contains('j'))
            {
                IList<PartProductGoogleModel> byCat = (from x in all
                                                       where x.AtrJ.Contains(category)
                                                       select x).ToList();
                foreach (var prod in byCat)
                {
                    if (!byCategory.ContainsKey(prod.Name))
                    {
                        byCategory.Add(prod.Name, prod);
                    }
                }
            }

            if (atrybutes.ToLower().Contains('k'))
            {
                IList<PartProductGoogleModel> byCat = (from x in all
                                                       where x.AtrK.Contains(category)
                                                       select x).ToList();
                foreach (var prod in byCat)
                {
                    if (!byCategory.ContainsKey(prod.Name))
                    {
                        byCategory.Add(prod.Name, prod);
                    }
                }
            }

            if (atrybutes.ToLower().Contains('l'))
            {
                IList<PartProductGoogleModel> byCat = (from x in all
                                                       where x.AtrL.Contains(category)
                                                       select x).ToList();
                foreach (var prod in byCat)
                {
                    if (!byCategory.ContainsKey(prod.Name))
                    {
                        byCategory.Add(prod.Name, prod);
                    }
                }
            }

            if (atrybutes.ToLower().Contains('m'))
            {
                IList<PartProductGoogleModel> byCat = (from x in all
                                                       where x.AtrM.Contains(category)
                                                       select x).ToList();
                foreach (var prod in byCat)
                {
                    if (!byCategory.ContainsKey(prod.Name))
                    {
                        byCategory.Add(prod.Name, prod);
                    }
                }
            }

            if (atrybutes.ToLower().Contains('n'))
            {
                IList<PartProductGoogleModel> byCat = (from x in all
                                                       where x.AtrN.Contains(category)
                                                       select x).ToList();
                foreach (var prod in byCat)
                {
                    if (!byCategory.ContainsKey(prod.Name))
                    {
                        byCategory.Add(prod.Name, prod);
                    }
                }
            }

            if (atrybutes.ToLower().Contains('o'))
            {
                IList<PartProductGoogleModel> byCat = (from x in all
                                                       where x.AtrO.Contains(category)
                                                       select x).ToList();
                foreach (var prod in byCat)
                {
                    if (!byCategory.ContainsKey(prod.Name))
                    {
                        byCategory.Add(prod.Name, prod);
                    }
                }
            }

            if (atrybutes.ToLower().Contains('p'))
            {
                IList<PartProductGoogleModel> byCat = (from x in all
                                                       where x.AtrP.Contains(category)
                                                       select x).ToList();
                foreach (var prod in byCat)
                {
                    if (!byCategory.ContainsKey(prod.Name))
                    {
                        byCategory.Add(prod.Name, prod);
                    }
                }
            }

            if (atrybutes.ToLower().Contains('q'))
            {
                IList<PartProductGoogleModel> byCat = (from x in all
                                                       where x.AtrQ.Contains(category)
                                                       select x).ToList();
                foreach (var prod in byCat)
                {
                    if (!byCategory.ContainsKey(prod.Name))
                    {
                        byCategory.Add(prod.Name, prod);
                    }
                }
            }

            if (atrybutes.ToLower().Contains('r'))
            {
                IList<PartProductGoogleModel> byCat = (from x in all
                                                       where x.AtrR.Contains(category)
                                                       select x).ToList();
                foreach (var prod in byCat)
                {
                    if (!byCategory.ContainsKey(prod.Name))
                    {
                        byCategory.Add(prod.Name, prod);
                    }
                }
            }

            if (atrybutes.ToLower().Contains('s'))
            {
                IList<PartProductGoogleModel> byCat = (from x in all
                                                       where x.AtrS.Contains(category)
                                                       select x).ToList();
                foreach (var prod in byCat)
                {
                    if (!byCategory.ContainsKey(prod.Name))
                    {
                        byCategory.Add(prod.Name, prod);
                    }
                }
            }

            if (atrybutes.ToLower().Contains('t'))
            {
                IList<PartProductGoogleModel> byCat = (from x in all
                                                       where x.AtrT.Contains(category)
                                                       select x).ToList();
                foreach (var prod in byCat)
                {
                    if (!byCategory.ContainsKey(prod.Name))
                    {
                        byCategory.Add(prod.Name, prod);
                    }
                }
            }

            
        }
            foreach (var x in byCategory.Values)
            {
                products_all.Add(BasketService.ConvertArticle(x as PartProductGoogleModel));
            }

            return products_all;
        }

        const int take = 50;
        private IList<BasketItemModel> VersionList(string article_name , string ver1, string ver2 )
        {

            var cmlist = GetAllProducts();

            IList<BasketItemModel> products_all = new List<BasketItemModel>();

            IList<PartProductGoogleModel> byName = new List<PartProductGoogleModel>();

            if(!string.IsNullOrEmpty(article_name) && (string.IsNullOrEmpty(ver1) && string.IsNullOrEmpty(ver2))){
               byName = (from x in cmlist where x.Gname == article_name
                      select x).Take(take).ToList();
            }else if (!string.IsNullOrEmpty(article_name)){
                 
                byName = (from x in cmlist where x.Gname == article_name
                      select x).ToList();
            }




            foreach (var x in byName)
            {
                if ((string.IsNullOrEmpty(ver1) && string.IsNullOrEmpty(ver2)) 
                    )
                {
                
                    products_all.Add(BasketService.ConvertArticle(x as PartProductGoogleModel));
                    continue;
                }
                //todo split
                var prod = x as PartProductGoogleModel;
                //product.AtrF = version1;
                //product.AtrG = version2;
                if (ver1.Contains(prod.AtrF) && string.IsNullOrEmpty(ver2))
                {
                    products_all.Add(BasketService.ConvertArticle(prod));
                    continue;
                }
                
                if (string.IsNullOrEmpty(ver1) && ver2.Contains(prod.AtrG))
                {
                    products_all.Add(BasketService.ConvertArticle(prod));
                    continue;
                }

                if (ver1.Contains(prod.AtrF) && ver2 .Contains(prod.AtrG))
                {
                    products_all.Add(BasketService.ConvertArticle(prod));
                }
            }
            return products_all;
        }

        public ActionResult Article_Category_Json(JsonSearchInputModel model)
        {
            return Json(CategoryList(model.Category, model.Page, model.PageSize,model.Atrs));
        }

        public ActionResult Article_Version_Json(JsonSearchInputModel model)
        {
          return Json(VersionList(model.Category, model.Ver1, model.Ver2));
            //return null;
        }
        #endregion
        #region  import


        public ActionResult Import()
        {
            var path = Server.MapPath("~") + @"\Upload\import\";

            ProcessVersionFile(path);
            ProcessFiles(path);

            return Content("Sukces");
        }


        Dictionary<string, string> dictVersions = new Dictionary<string, string>(); 
        
        const string versionFileName = "v.txt";
        private void ProcessVersionFile(string path) {

            using (var sr = new StreamReader(path+"\\"+versionFileName))
            { 
                var line = string.Empty;
                while((line = sr.ReadLine())!= null ){
                  var versionArray = line.Split(spliter);

                  var alias = versionArray[GetAlfabetIndex("c")];
                  var key = versionArray[GetAlfabetIndex("b")];

                  if (!string.IsNullOrEmpty(alias)) {
                      dictVersions.Add(key, alias);
                  }
                }
            }
        }

        private string GetAlias(string name){

            if (dictVersions.ContainsKey(name)) {

                return dictVersions[name];
            }
            return name;
        }

        private void ProcessFiles(string path)
        {

            var fileList = Directory.GetFiles(path);

            foreach (var filePath in fileList)
            {
                ProcessFile(filePath);
            }

        }

        const int catIndex = 3;
        const string zoneName = "PostContent";
        char spliter = '\t';

        private void ProcessFile(string fileName)
        {

            if (Path.GetExtension(fileName) != ".csv" && Path.GetExtension(fileName) != ".txt" && Path.GetFileName(fileName)=="v.txt")
            {
                return;
            }

            var grantParent = N2.Context.Definitions.CreateInstance<ContentPage>(N2.Find.RootItem);
            var name = Path.GetFileName(fileName).Replace(Path.GetExtension(fileName), "");
            name += string.Format("{0:d-M-yyyy-HH-mm-ss}", DateTime.Now);
            grantParent.Name = name;
            grantParent.Title = name;
            N2.Context.Persister.Save(grantParent);


            var parent = N2.Context.Definitions.CreateInstance<ContentPage>(grantParent);
            var name2 = Path.GetFileName(fileName).Replace(Path.GetExtension(fileName), "");
            name2 += string.Format("{0:d-M-yyyy-HH-mm-ss}", DateTime.Now);
            parent.Name = name2;
            parent.Title = name2;
            N2.Context.Persister.Save(parent);


            using (var sr = new StreamReader(fileName))
            {
                string line = "";
                line = sr.ReadLine();
                firstLine = line.Split(spliter);

                while ((line = sr.ReadLine()) != null)
                {
                    ProcessLine(parent, line);
                }
            }
        }

        private ContentPage CreateVersionNode(ContentPage allProductNode, string[] lineArray)
        {
            try
            {
                var versionParent = N2.Context.Definitions.CreateInstance<ContentPage>(allProductNode);
                
                var name = lineArray[GetAlfabetIndex("b")];
                var encodedName = Utils.GetEncodedName(name);

                versionParent.Title = name;
                versionParent.Name = encodedName;

                var partVersion = new PartVersionModel();
                partVersion.MainName = name;
                partVersion.ZoneName = zoneName;

                partVersion.AddTo(versionParent);
                versionParent.State = ContentState.Published;
                N2.Context.Persister.Save(versionParent);

                return versionParent;
            }
            catch (Exception e) {
                logger.Error(e);
            }
            return null;
        }

        string[] firstLine = new string[35];
       

        private void ProcessLine(ContentPage allProductNode, string line)
        {

         var cellSpliter = ',';
            
            var lineArray = line.Split(spliter);//Split(';');
            
            var verionNode = CreateVersionNode(allProductNode, lineArray);
            if (verionNode != null)
            {
                //kolory tapicerki
                var color_material = lineArray[GetAlfabetIndex("F")];
                var color_M = color_material.Split(cellSpliter);

                var color_Wood = lineArray[GetAlfabetIndex("G")];
                var color_W = color_Wood.Split(cellSpliter);
                //c d
                foreach (var mat in color_M)
                {
                    foreach (var wood in color_W)
                    {
                        CreateNonde(verionNode, lineArray, mat, wood);
                    }
                }
            }
        }

        const string jpg = ".jpg";
        private void CreateNonde(ContentPage allProductNode, string[] lineArray, string version1, string version2)
        {
            try
            {
                var productParent = N2.Context.Definitions.CreateInstance<ContentPage>(allProductNode);
                var product = new PartProductGoogleModel();

                        //nazwa
                        var str = lineArray[GetAlfabetIndex("b")];
                        var name = str + "-" + GetAlias(version1) + "-" + GetAlias( version2);
                        var encodedName = Utils.GetEncodedName(name);
                        var imageName = Utils.GetEncodedName(str);

                        productParent.Title = name;
                        productParent.Name = encodedName;

                        product.Gname = str;
                        product.Title = str;
                        product.Name = encodedName;

                        product.InSale = true;

                        if(  lineArray[GetAlfabetIndex("u")].Contains(version1)
                          || lineArray[GetAlfabetIndex("v")].Contains(version2)){
                          product.InSale = false;
                        }
                        //var path = Server.MapPath("~") + @"\Upload\import\";

                        product.Image = @"/Upload/meble/" + imageName + jpg;

                        product.AtrF = version1;
                        product.AtrG = version2;
                        product.Image2 = @"/Upload/wzorniki/" + Utils.GetEncodedName(GetImageNames(version1)) + jpg;
                        product.Image3 = @"/Upload/wzorniki/" + Utils.GetEncodedName(version2) + jpg;

                        //todo identfifier
                        product.Identifier = encodedName;

                       // "D. obecna cena netto", 4)]
                       product.AtrD = lineArray[GetAlfabetIndex("d")];
                       //"E. obecna cena", 5)]
                       product.CurrentPrice  = lineArray[GetAlfabetIndex("e")];
                       //"W. stara cena  ", 6)]
                       product.OldPrice = lineArray[GetAlfabetIndex("w")];


                       product.AtrH = GetColVal("H", firstLine, lineArray);
                       product.AtrI = GetColVal("I", firstLine, lineArray);
                       product.AtrJ = GetColVal("J", firstLine, lineArray);
                       product.AtrK = GetColVal("K", firstLine, lineArray);
                       product.AtrL = GetColVal("L", firstLine, lineArray);
                       product.AtrM = GetColVal("M", firstLine, lineArray);
                       product.AtrN = GetColVal("N", firstLine, lineArray);
                       product.AtrO = GetColVal("O", firstLine, lineArray);
                       product.AtrP = GetColVal("P", firstLine, lineArray);
                       product.AtrQ = GetColVal("Q", firstLine, lineArray);
                       product.AtrR = GetColVal("R", firstLine, lineArray);
                       product.AtrS = GetColVal("S", firstLine, lineArray);
                       product.AtrT = GetColVal("T", firstLine, lineArray);

                       product.Brand = GetColVal("X", firstLine, lineArray);

                    product.ZoneName = zoneName;
                    product.AddTo(productParent);
                    productParent.State = ContentState.Published;

                    N2.Context.Persister.Save(productParent);
                
            }
            catch (Exception e) //Fixme 
            {
                logger.Error(e);
            }
        }


        private int GetAlfabetIndex(string st)
        {
            string alfabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            return alfabet.IndexOf(st.ToUpper());
        }

        string GetColVal(string col, string[] header, string[] line ) {
           var i = GetAlfabetIndex(col);
           return "<b>" + header[i] + "</b>" + line[i]  ;
        }

        private string GetHeader(string kolumn)
        {
            return firstLine[GetAlfabetIndex(kolumn)];
        }

        private string GetImageNames(string name)
        {
            var ret = name;
            for (int i = 1; i <= 15; i++)
            {
                if (name == Convert.ToString(i))
                {
                    if (i < 10) {
                        ret = "00" + name;
                        break;
                    }
                    if (i >= 10) {
                        ret = "0" + name;
                        break;
                    }
                }
            }
            return ret;
        }

        #endregion
    }
}
